package br.com.petsis.funcionalidades.manterPacote;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.servlet.ServletContext;

import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Out;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.security.Restrict;
import org.jboss.seam.faces.FacesMessages;
import org.jboss.seam.international.StatusMessage.Severity;

import br.com.petsis.entity.Cliente;
import br.com.petsis.entity.Empresa;
import br.com.petsis.entity.FormaPagamento;
import br.com.petsis.entity.Pacote;
import br.com.petsis.entity.Perfil;
import br.com.petsis.entity.Pet;
import br.com.petsis.entity.Raca;
import br.com.petsis.utilitarios.UtilString;

@Name("manterPacoteController")
@Scope(ScopeType.CONVERSATION)
@Restrict(value="#{!identity.hasRole('"+Perfil.PERFIL_VETERINARIA+"')}")
public class ManterPacoteController {
	
	private static final String QRY_PACOTES = "select p.id_pacote,p.id_cliente,p.dta_inicio,p.dta_fim,p.vlr_pacote,p.id_forma_pagamento from pacote p where p.id_empresa = :idEmpresa and p.flg_ativo = 'T' order by p.dta_inicio DESC";
	private static final String QRY_CLIENTES = "select c.id_cliente,c.dsc_nome from cliente c where c.id_empresa = :idEmpresa and c.flg_ativo = 'T' order by c.dsc_nome";
	private static final String QRY_PETS = "select p.id_pet,p.dsc_nome from pet p where p.id_cliente = :idCliente and p.flg_ativo = 'T' order by p.dsc_nome";
	private static final String QRY_PACOTES_VALIDACAO = "SELECT p FROM Pacote p where p.empresa.idEmpresa = :idEmpresa and p.cliente.idCliente = :idCliente and p.flgAtivo = 'T' and((p.dtaInicio <= :dtaInicio AND p.dtaFim >= :dtaInicio) OR (p.dtaInicio <= :dtaFim AND p.dtaFim >= :dtaFim) OR (p.dtaInicio >= :dtaInicio AND p.dtaFim <= :dtaFim))";
	
	private static final String PARAMETER_ID_CLIENTE = "idCliente";
	private static final String PARAMETER_ID_EMPRESA = "idEmpresa";
	private static final String PARAMETER_DTA_INICIO = "dtaInicio";
	private static final String PARAMETER_DTA_FIM = "dtaFim";

	@In(create=true)
	private EntityManager entityManager;
	
	private Pacote pacoteEdicao;
	
	@In(required=false)
	@Out(required=false)
	private Pacote pacoteSelecionado;
	
	private List<Pacote> listaPacotes;
	
	private List<SelectItem> listaClientes;
	
	private List<SelectItem> listaPets;
	
	private List<SelectItem> listaFormasPagamento;
	
	private Integer clienteSelecionado;
	
	private Integer petSelecionado;
	
	private boolean selecionadoTodos;
	
	private Integer idFormaPagamento;
	
	private String filtroNome;
	
	private String filtroDataInicio;
	
	private String filtroDataFim;
	
	private String filtroValor;
	
	public String getFiltroNome() {
		return filtroNome;
	}

	public void setFiltroNome(String filtroNome) {
		this.filtroNome = filtroNome;
	}

	public String getFiltroDataInicio() {
		return filtroDataInicio;
	}

	public void setFiltroDataInicio(String filtroDataInicio) {
		this.filtroDataInicio = filtroDataInicio;
	}

	public String getFiltroDataFim() {
		return filtroDataFim;
	}

	public void setFiltroDataFim(String filtroDataFim) {
		this.filtroDataFim = filtroDataFim;
	}

	public String getFiltroValor() {
		return filtroValor;
	}

	public void setFiltroValor(String filtroValor) {
		this.filtroValor = filtroValor;
	}
	
	public boolean filtrarPacotesPorNome(Object current){
		Pacote pacote = (Pacote)current;
		if(getFiltroNome()== null || getFiltroNome().isEmpty()){
			return true;
		}
		if(pacote.getCliente().getDscNome().toLowerCase().contains(getFiltroNome().toLowerCase())){
			return true;
		}else{
			return false;
		}
	}
	
	public boolean filtrarPacotesPorDataInicio(Object current){
		Pacote pacote = (Pacote)current;
		if(getFiltroDataInicio() == null || getFiltroDataInicio().isEmpty()){
			return true;
		}
		SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
		if(sdf.format(pacote.getDtaInicio()).contains(getFiltroDataInicio().toLowerCase())){
			return true;
		}else{
			return false;
		}
	}
	
	public boolean filtrarPacotesPorDataFim(Object current){
		Pacote pacote = (Pacote)current;
		if(getFiltroDataFim() == null || getFiltroDataFim().isEmpty()){
			return true;
		}
		SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
		if(sdf.format(pacote.getDtaFim()).contains(getFiltroDataFim().toLowerCase())){
			return true;
		}else{
			return false;
		}
	}
	
	public boolean filtrarPacotesPorValor(Object current){
		Pacote pacote = (Pacote)current;
		if(getFiltroValor() == null || getFiltroValor().isEmpty()){
			return true;
		}
		if(pacote.getVlrPacote().toString().contains(getFiltroValor().replace(",", "."))){
			return true;
		}else{
			return false;
		}
	}

	@In(required=false)
	private Empresa empresaSessao;
	
	public void onLoad(){
		
	}
	
	public void onLoadList(){
		pacoteSelecionado = null;
		pacoteEdicao = new Pacote();
	}
	
	public String novoPacote(){
		return "novo";
	}
	
	public void excluir(){
		List<Pacote> pacotesRemocao = new ArrayList<Pacote>();
		for(Pacote p : getListaPacotes()){
			if(p.isSelecionado()){
				pacotesRemocao.add(p);
				p.setFlgAtivo('F');
				entityManager.merge(p);
			}
		}
		getListaPacotes().removeAll(pacotesRemocao);
		entityManager.flush();
	}
	
	public void buscarOutrasInformacoes(){
		if(empresaSessao == null){
			return;
		}
		if(getClienteSelecionado() != null){
			List<Pacote> pacotes = entityManager.createQuery("select p from Pacote p where p.empresa.idEmpresa = :idEmpresa and p.cliente.idCliente = :idCliente and p.dscCpf is not null ")
				.setParameter("idCliente", getClienteSelecionado())
				.setParameter(PARAMETER_ID_EMPRESA, empresaSessao.getIdEmpresa())
				.getResultList();
			if(pacotes != null && pacotes.size() > 0){
				getPacoteEdicao().setDscCpf(pacotes.get(0).getDscCpf());
				getPacoteEdicao().setDscRg(pacotes.get(0).getDscRg());
				getPacoteEdicao().setDscOrgaoExpRg(pacotes.get(0).getDscOrgaoExpRg());
				getPacoteEdicao().setDscUfEndereco(pacotes.get(0).getDscUfEndereco());
				getPacoteEdicao().setDiaPagamentoMes(pacotes.get(0).getDiaPagamentoMes());
			}else{
				getPacoteEdicao().setDscCpf(null);
				getPacoteEdicao().setDscRg(null);
				getPacoteEdicao().setDscOrgaoExpRg(null);
				getPacoteEdicao().setDscUfEndereco(null);
				getPacoteEdicao().setDiaPagamentoMes(null);
			}
		}else{
			getPacoteEdicao().setDscCpf(null);
			getPacoteEdicao().setDscRg(null);
			getPacoteEdicao().setDscOrgaoExpRg(null);
			getPacoteEdicao().setDscUfEndereco(null);
			getPacoteEdicao().setDiaPagamentoMes(null);
		}
	}
	
	public String salvar(){
		if(empresaSessao == null){
			FacesMessages.instance().add(Severity.ERROR,"Somente empresas podem salvar pacotes.");
			return null;
		}
		Cliente cliente = entityManager.find(Cliente.class, clienteSelecionado);
		if(pacoteEdicao.getDtaPagamento() != null &&
				getIdFormaPagamento() == null){
			FacesMessages.instance().add(Severity.ERROR,"O campo Forma de Pagamento é de preenchimento obrigatório.");
			return null;
		}
		pacoteEdicao.setFormaPagamento(getIdFormaPagamento() != null ? entityManager.find(FormaPagamento.class, getIdFormaPagamento()) : null);
		pacoteEdicao.setEmpresa(empresaSessao);
		pacoteEdicao.setPet(entityManager.find(Pet.class, getPetSelecionado()));
		try{
			if(pacoteEdicao.getIdPacote() == null){
				entityManager.createQuery(QRY_PACOTES_VALIDACAO)
					.setParameter(PARAMETER_ID_CLIENTE, cliente.getIdCliente())
					.setParameter(PARAMETER_ID_EMPRESA, empresaSessao.getIdEmpresa())
					.setParameter(PARAMETER_DTA_INICIO, pacoteEdicao.getDtaInicio())
					.setParameter(PARAMETER_DTA_FIM, pacoteEdicao.getDtaFim())
					.getSingleResult();
				FacesMessages.instance().add(Severity.ERROR,"As datas de início e fim não podem coincidir com as datas de outros pacotes do mesmo cliente.");
				return null;
			}else{
				pacoteEdicao.setCliente(null);
				pacoteEdicao.setCliente(cliente);
				pacoteEdicao.setFlgAtivo('T');
				Pacote pacoteSalvo = entityManager.merge(pacoteEdicao);
				entityManager.flush();
				/*if(!getListaPacotes().contains(pacoteSalvo)){
					getListaPacotes().add(pacoteSalvo);
				}*/
				pacoteEdicao = new Pacote();
				clienteSelecionado = null;
				setIdFormaPagamento(null);
				setListaPacotes(null);
				FacesMessages.instance().add(Severity.INFO,"Pacote salvo com sucesso.");
				return "persisted";
			}
		}catch(NoResultException e){
			pacoteEdicao.setCliente(null);
			pacoteEdicao.setCliente(cliente);
			pacoteEdicao.setFlgAtivo('T');
			Pacote pacoteSalvo = entityManager.merge(pacoteEdicao);
			entityManager.flush();
			if(!getListaPacotes().contains(pacoteSalvo)){
				getListaPacotes().add(pacoteSalvo);
			}
			pacoteEdicao = new Pacote();
			clienteSelecionado = null;
			setIdFormaPagamento(null);
			setListaPacotes(null);
			FacesMessages.instance().add(Severity.INFO,"Pacote salvo com sucesso.");
			return "persisted";
		}
	}
	
	public String cancelar(){
		pacoteEdicao = new Pacote();
		clienteSelecionado = null;
		return "voltar";
	}
	
	public String editar(Pacote pacote){
		pacoteEdicao = entityManager.find(Pacote.class, pacote.getIdPacote());
		setIdFormaPagamento(pacoteEdicao.getFormaPagamento() != null ? pacoteEdicao.getFormaPagamento().getIdFormaPagamento() : null);
		clienteSelecionado = pacoteEdicao.getCliente().getIdCliente();
		petSelecionado = pacoteEdicao.getPet() != null ? pacoteEdicao.getPet().getIdPet() : null;
		return "editar";
	}
	
	public void selecionaTodos(){
		for(Pacote p : getListaPacotes()){
			if(isSelecionadoTodos()){
				p.setSelecionado(true);
			}else{
				p.setSelecionado(false);
			}
		}
	}

	public boolean isSelecionadoTodos() {
		return selecionadoTodos;
	}

	public void setSelecionadoTodos(boolean selecionadoTodos) {
		this.selecionadoTodos = selecionadoTodos;
	}

	public Pacote getPacoteEdicao() {
		if (pacoteEdicao == null) {
			pacoteEdicao = new Pacote();
		}
		return pacoteEdicao;
	}

	public void setPacoteEdicao(Pacote pacoteEdicao) {
		this.pacoteEdicao = pacoteEdicao;
	}

	public Pacote getPacoteSelecionado() {
		return pacoteSelecionado;
	}

	public void setPacoteSelecionado(Pacote pacoteSelecionado) {
		this.pacoteSelecionado = pacoteSelecionado;
	}

	public List<Pacote> getListaPacotes() {
		if (listaPacotes == null) {
			listaPacotes = new ArrayList<Pacote>();		
			if(empresaSessao != null){
				List<Object[]> lista = entityManager.createNativeQuery(QRY_PACOTES)
					.setParameter(PARAMETER_ID_EMPRESA, empresaSessao.getIdEmpresa())
					.getResultList();
				Pacote p;
				for(Object[] o : lista){
					p = new Pacote();
					p.setIdPacote(Integer.parseInt(o[0].toString()));
					Cliente c = new Cliente();
					c.setDscNome(o[1] != null ? recuperaNomeCliente(Integer.parseInt(o[1].toString())) : null);
					p.setCliente(c);
					FormaPagamento fp = new FormaPagamento();
					fp.setDscFormaPagamento(o[5] != null ? recuperaNomeFormaPagamento(Integer.parseInt(o[5].toString())) : null);
					p.setFormaPagamento(fp);
					p.setDtaInicio(o[2] != null ? (Date)o[2] : null);
					p.setDtaFim(o[3] != null ? (Date)o[3] : null);
					p.setVlrPacote(o[4] != null ? Float.parseFloat(o[4].toString()) : null);
					listaPacotes.add(p);
				}
			}
		}
		return listaPacotes;
	}
	
	public String recuperaNomeCliente(Integer id){
		try{
			Object retorno = entityManager.createNativeQuery("select c.dsc_nome from cliente c where c.id_cliente = :idCliente")
				.setParameter("idCliente", id)
				.getSingleResult();
			return retorno != null ? retorno.toString() : null;
		}catch(NoResultException e){
			return null;
		}
	}
	
	public String recuperaNomeFormaPagamento(Integer id){
		try{
			Object retorno = entityManager.createNativeQuery("select f.dsc_forma_pagamento from forma_pagamento f where f.id_forma_pagamento = :id")
				.setParameter("id", id)
				.getSingleResult();
			return retorno != null ? retorno.toString() : null;
		}catch(NoResultException e){
			return null;
		}
	}

	public void setListaPacotes(List<Pacote> listaPacotes) {
		this.listaPacotes = listaPacotes;
	}

	public Integer getClienteSelecionado() {
		return clienteSelecionado;
	}

	public void setClienteSelecionado(Integer clienteSelecionado) {
		this.clienteSelecionado = clienteSelecionado;
	}

	public Integer getPetSelecionado() {
		return petSelecionado;
	}

	public void setPetSelecionado(Integer petSelecionado) {
		this.petSelecionado = petSelecionado;
	}

	public Integer getIdFormaPagamento() {
		return idFormaPagamento;
	}

	public void setIdFormaPagamento(Integer idFormaPagamento) {
		this.idFormaPagamento = idFormaPagamento;
	}

	public List<SelectItem> getListaClientes() {
		if (listaClientes == null) {
			listaClientes = new ArrayList<SelectItem>();
			listaClientes.add(new SelectItem(null,"Selecione"));
			if(empresaSessao != null){
				List<Object[]> clientes = entityManager.createNativeQuery(QRY_CLIENTES)
					.setParameter(PARAMETER_ID_EMPRESA, empresaSessao.getIdEmpresa())
					.getResultList();
				for(Object[] o : clientes){
					listaClientes.add(new SelectItem(Integer.parseInt(o[0].toString()), 
							o[1] != null ? o[1].toString() : null));
				}
			}
		}
		return listaClientes;
	}

	public void setListaClientes(List<SelectItem> listaClientes) {
		this.listaClientes = listaClientes;
	}

	public List<SelectItem> getListaPets() {
//		if (listaPets == null) {
			listaPets = new ArrayList<SelectItem>();
			listaPets.add(new SelectItem(null,"Selecione"));
			if(getClienteSelecionado() != null){
				List<Object[]> pets = entityManager.createNativeQuery(QRY_PETS)
					.setParameter(PARAMETER_ID_CLIENTE, getClienteSelecionado())
					.getResultList();
				for(Object[] o : pets){
					listaPets.add(new SelectItem(Integer.parseInt(o[0].toString()), 
							o[1] != null ? o[1].toString() : null));
				}
			}
//		}
		return listaPets;
	}

	public void setListaPets(List<SelectItem> listaPets) {
		this.listaPets = listaPets;
	}

	public List<SelectItem> getListaFormasPagamento() {
		if (listaFormasPagamento == null) {
			listaFormasPagamento = new ArrayList<SelectItem>();
			listaFormasPagamento.add(new SelectItem(null,"Selecione"));
			List<FormaPagamento> lista = entityManager.createQuery("select f from FormaPagamento f where f.flgAtivo = 'T'").getResultList();
			for(FormaPagamento f : lista){
				listaFormasPagamento.add(new SelectItem(f.getIdFormaPagamento(),f.getDscFormaPagamento()));
			}
		}
		return listaFormasPagamento;
	}

	public void setListaFormasPagamento(List<SelectItem> listaFormasPagamento) {
		this.listaFormasPagamento = listaFormasPagamento;
	}
	
	public String recuperaCaminhoImagem(String nomeImagem){
		FacesContext context1 = FacesContext.getCurrentInstance();
		String caminhoAplicacao = ((ServletContext) context1.getExternalContext().getContext()).getRealPath("/");
		return caminhoAplicacao+"/img/"+nomeImagem;
	}
	
	public String gerarContrato(Pacote pacote){
		pacoteSelecionado = entityManager.find(Pacote.class, pacote.getIdPacote());
		if(pacoteSelecionado.getPet() == null){
			pacoteSelecionado.setPet(new Pet());
			pacoteSelecionado.getPet().setRaca(new Raca());
		}
		return "contrato";
	}
	
	public String valorPorExtenso(Float valor){
		Double vlrDouble = Double.valueOf(valor);
		return UtilString.valorPorExtenso(vlrDouble);
	}
	
}
